#pragma once

#include "../common/D3D9Plugin/D3D9Plugin.h"
#include "../common/DepthTexture/DepthTexture.h"
#include "../common/ScreenTexture/ScreenTexture.h"

extern "C" __declspec(dllexport) IDirect3D9BasePlugin* CreatePlugin(IServiceLocator& ar_ServiceLocator);

class DOF2Plugin
	: public D3D9Plugin
{
protected:
	IShaderSystem* shaderSystem;
	ScreenTexture* screenTexture;
	ScreenTexture* blurTexture;
	DepthTexture* depthTexture;
	Filter* dofFilter;

	bool showDepthOnly;
	bool showBlurOnly;
	float focusPlane;
	float farPlane;
	float aperture;
	float blurDownSampling;

public:

	DOF2Plugin(IServiceLocator& serviceLocator)
		: D3D9Plugin(serviceLocator, L"DOF2", L"Higher Quality Depth of Field")
	{
		blurDownSampling = 4;
		AddUIParameter(&showDepthOnly, L"showDepthOnly", L"Show depth data only", false);
		AddUIParameter(&showBlurOnly, L"showBlurOnly", L"Show blur pre buffer only", false);
		AddUIParameter(&focusPlane, L"focusPlane", L"Focus Plane", 1, 100, 1, 0.01f);
		AddUIParameter(&farPlane, L"farPlane", L"Far Plane", 1, 100, 10, 0.01f);
		AddUIParameter(&aperture, L"aperture", L"aperture", 1, 10, 1, 0.001f);
	}

	void Activate()
	{
		shaderSystem = new ShaderSystem(mr_Device_);
		depthTexture = new DepthTexture(mr_Device_, environment, *shaderSystem, "Plugins\\SSAO");
		screenTexture = new ScreenTexture(mr_Device_);
		blurTexture = new ScreenTexture(mr_Device_, blurDownSampling);

		filterManager->AddParameter("ScreenTexture", screenTexture->GetTexture());
		filterManager->AddParameter("BlurTexture", blurTexture->GetTexture());
		filterManager->AddParameter("DepthTexture", depthTexture->GetTexture());
		filterManager->AddParameter("FarPlane", &farPlane);
		filterManager->AddParameter("FocusPlane", &focusPlane);
		filterManager->AddParameter("Aperture", &aperture);
		dofFilter = filterManager->LoadFilter("DOF.fx");
	}

	virtual void PostProcess()
	{
		screenTexture->UpdateTexture();
		depthTexture->CalculateDepthBufferData();

		if(showDepthOnly)
		{
			dofFilter->Render("DepthOnly");
		}
		else
		{
			dofFilter->Render("Blur", blurDownSampling);
			blurTexture->UpdateTexture();
			if(!showBlurOnly)
			{
				dofFilter->Render("DepthOfField");
			}
		}
	}

	void Deactivate()
	{
		filterManager->ClearParameters();
		delete depthTexture;
		delete screenTexture;
		delete dofFilter;
		delete shaderSystem;
	}
};
